#include "PieceGL.h"
#include "glwidget.h"
#include "dim.h"

#include <QtOpenGL>
#include <string>

// Initialisation statique de la pièce séléctionnée
PieceGL * PieceGL::selectedPiece = NULL ;

/* Constructeur : Piece parente, couleur, PieceGL enfant */
PieceGL::PieceGL (Piece * parent, bool joueur, PieceGL * c): monParent(parent), selected(false), child(c), pickingdessine(false) {
	couleur = joueur ;
}

/* Destructeur */
PieceGL::~PieceGL() {
	// Si le la liste d'affichage pour le picking a été dessinée, alors on la supprime
	if (pickingdessine)
		glDeleteLists(listpicking, 1) ;
}

/* Description des sommets de la pièce */
void PieceGL::drawPiece()
{
	/* Récupération des champs static des enfants */
	int & numFaces (child->getnf()) ;	// Réference sur le nombre de faces
	GLfloat * Verts (child->getv()) ;	// Pointeur sur le tableau bidimentionnel de sommets
	int * Faces (child->getf()) ;		// Pointeur sur le tableau bidimentionnel de faces
	
	glBegin(GL_TRIANGLES);
		for (int j(0) ; j < numFaces-1 ; j++) {
			for (int i(0) ; i < 3 ; i++)
			{
				glVertex3fv(Verts+(Faces[j*3+i]*3));
			}
		}
	glEnd();
}

/* Affiche la pièce */
void PieceGL::draw() {
	glEnable(GL_BLEND) ; // Pour la transparence
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ;
	
		double alpha = 0.8; // Niveau de la transparence
		if (!child->isd()){ // Si la liste d'affichage n'a pas encore été créée
			child->make() ; // On créer la liste d'affichage
		}
		glPushMatrix() ;
			if (couleur == BLANC) {	// Si on dessine une pièce blanche
				(selected)?glColor4d(0.6, 1, 1, alpha): glColor4d(1, 1, 1, alpha);	// En fonction de l'état de sélection
			}
			else {	// Si on dessine une pièce noire
				glRotatef(180, 0,1,0);
				(selected)?glColor4d(0.4, 0, 0, alpha): glColor4d(0, 0, 0, alpha);	// En fonction de l'état de sélection
			}
			glCallList(child->getl()) ;	// Execute la liste d'affichage de la pièce
		glPopMatrix() ;
	
	glDisable(GL_BLEND) ;
}

/* Gère la selection */
void PieceGL::toggleSelect() {
	selected = !selected ; // Inverse l'état de sélection
	
	if (selectedPiece && selectedPiece != this)	// Si la pièce sélectionnée parmis toutes les pièces est différente de celle-ci
		selectedPiece->setSelected(false);	// alors la pièce sélectionnée est déselectionnée
	
	if (selected)	// Si la pièce est finallement sélectionnée
		selectedPiece = this ;	// alors elle devient la pièce selectionnée
}

/* Affiche la pièce pour le picking */
void PieceGL::drawPicking() {
	if (!pickingdessine)
		makePicking() ;
	
	glCallList(listpicking) ;
}

/*Déplace la piece aux coordonnées x, et y de l'échiquier. */
void PieceGL::movetoPosition (int x, int y) {
	double pas = ew/nbPiece ;
	double pasInitial = pas / 2.0 ;
	glTranslated(pasInitial+x*pas, 0.7, -(pasInitial+y*pas)) ;
}

/* Fabrique la liste d'affichage, pour le picking */
void PieceGL::makePicking(){
	listpicking = glGenLists(1) ;	// Génère un numéro de liste
	if (!listpicking)	// Si la génération à échouée
		throw std::string ("Erreur lors de la génération de la liste") ;	// On lance une exception
	glNewList ( listpicking, GL_COMPILE);	// On fabrique une nouvelle liste
	glPushAttrib ( GL_CURRENT_BIT );
		glLoadName((unsigned int)this) ; // le nom est l'adresse de l'objet
		glPushMatrix() ;
		glScalef(0.7, 0.4, 0.7) ;
		glutSolidCube(1) ;	// On dessine un cube
		glPopMatrix() ;
	glPopAttrib();
	glEndList();
	
	pickingdessine = true ;	
}

/* Génère la liste d'affichage de la pièce */
void PieceGL::make() {
	/* Récupération des champs static des enfants */
	bool & dessine (child->isd());	// Référence sur le boolean qui indique si la liste d'affichage a été créée
	int & list (child->getl()) ; // Référence sur la liste d'affichage
	
	list = glGenLists(1) ;	// Génère un numéro de liste
	if (!list)	// Si la génération à échouée
		throw std::string ("Erreur lors de la génération de la liste") ;	// On lance une exception
	glNewList ( list, GL_COMPILE);	// On fabrique une nouvelle liste
	glPushAttrib ( GL_CURRENT_BIT | GL_COLOR_BUFFER_BIT );
	drawPiece () ;	// On dessine la pièce
	glPopAttrib();
	glEndList();
	
	dessine = true ;	// indique que la liste d'affichage a été créée
}
